#include "thread_pool.h"

namespace umtl
{
	namespace parallel
	{
		//////////////////////////////////////////////////////////////////////////
		//

		critical_section thread_pool::_ct;

		//////////////////////////////////////////////////////////////////////////
		//

		thread_pool::thread_pool()
			: cpu_core_num_(0)
		{
			SYSTEM_INFO sysinfo;
			GetSystemInfo( &sysinfo );
			cpu_core_num_ = (short int)sysinfo.dwNumberOfProcessors;
		}

		//////////////////////////////////////////////////////////////////////////
		//

		void thread_pool::push( thread * t )
		{
			if( !t )
				return;

			lock_section( _ct );

			instance().threads_.push_back( t );
		}

		//////////////////////////////////////////////////////////////////////////
		//

		void thread_pool::push( thread ** t, size_t num = 1 )
		{
			if( !t || !*t )
				return;

			lock_section( _ct );

			thread_pool & inst = instance();

			for( size_t i=0; i<num; ++i )
			{
				if(t[i]) inst.threads_.push_back( t[i] );
			}
		}

		//////////////////////////////////////////////////////////////////////////
		//

		thread * thread_pool::pop()
		{
			lock_section( _ct );

			thread * t = 0;

			thread_pool & inst = instance();

			if( inst.threads_.empty() )
			{
				t = new thread();
			}
			else
			{
				t = inst.threads_.back();
				inst.threads_.pop_back();
			}

			return t;
		}

		//////////////////////////////////////////////////////////////////////////
		//

		void thread_pool::pop( thread** t, size_t num )
		{
			if( !t )
				return;

			lock_section( _ct );

			thread_pool & inst = instance();

			for( size_t i=0; i<num; ++i )
			{
				if( inst.threads_.empty() )
				{
					t[i] = new thread();
				}
				else
				{
					t[i] = inst.threads_.back();
					inst.threads_.pop_back();
				}
			}
		}

		//////////////////////////////////////////////////////////////////////////
		//

		thread_pool::~thread_pool()
		{
			for( Threads::iterator iter = threads_.begin(); iter != threads_.end(); ++iter )
				delete *iter;
		}

		//////////////////////////////////////////////////////////////////////////
	}
}